package com.adjaisd.scarecrow.service.impl;

import com.adjaisd.scarecrow.dto.QuotaCount;
import com.adjaisd.scarecrow.dto.QuotaInfo;
import com.adjaisd.scarecrow.entity.Device;
import com.adjaisd.scarecrow.entity.DeviceStatus;
import com.adjaisd.scarecrow.entity.Quota;
import com.adjaisd.scarecrow.mapper.DeviceMapper;
import com.adjaisd.scarecrow.mapper.DeviceStatusMapper;
import com.adjaisd.scarecrow.repo.TimeSeriesRepository;
import com.adjaisd.scarecrow.service.DeviceService;
import com.adjaisd.scarecrow.service.DeviceStatusService;
import com.adjaisd.scarecrow.service.QuotaService;
import com.adjaisd.scarecrow.vo.Pager;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author adjaisd
 * @since 2022-03-10
 */
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {

    @Autowired
    DeviceMapper deviceMapper;

    @Autowired
    DeviceStatusMapper deviceStatusMapper;

    @Override
    public List<Device> getAllDevice() {    // 获取所有设备
        QueryWrapper<Device> wrapper1 = new QueryWrapper<>();

        // 找到所有status状态为false的设备ID
        QueryWrapper<DeviceStatus> wrapper2 = new QueryWrapper<>();
        wrapper2.lambda().eq(DeviceStatus::getStatus, true);
        List<Long> includeID = deviceStatusMapper.selectList(wrapper2).stream().map(DeviceStatus::getId).collect(Collectors.toList());

        wrapper1.lambda().gt(Device::getBindTime, 0L)
                .in(Device::getId, includeID);
        return this.list(wrapper1);
    }

    @Override
    public Device getDeviceByID(Long deviceId) {
        QueryWrapper<Device> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Device::getId, deviceId)
                .gt(Device::getBindTime, 0L);
        List<Device> list = this.list(wrapper);
        if (list.size() == 0) return null;
        else return list.get(0);
    }

    @Override
    public Device getDeviceByNumber(Long number) {
        QueryWrapper<Device> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Device::getNumber, number);
        List<Device> list = this.list(wrapper);
        if (list.size() == 0) return null;
        else return list.get(0);
    }

    @Override
    public Device getDeviceByNumberUID(Long number, Long userId) {
        QueryWrapper<Device> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Device::getNumber, number)
                .eq(Device::getOwnerId, userId);
        List<Device> list = this.list(wrapper);
        if (list.size() == 0) return null;
        else return list.get(0);
    }

    @Override
    public List<Device> getDeviceListByUID(Long userId) {
        QueryWrapper<Device> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Device::getOwnerId, userId)
                .gt(Device::getBindTime, 0L)
                .orderByAsc(Device::getNumber);
        return this.list(wrapper);
    }

    @Override
    public Boolean addDevice(Device device) {
        return deviceMapper.insert(device) > 0;
    }

    @Override
    public Boolean delDevice(Long userId, Long number) {
        Device device = getDeviceByNumberUID(number, userId);
        if (device == null) return false;
        device.setBindTime(0L); // 绑定时间为0表示设备已删除
        return deviceMapper.updateById(device) > 0;
    }

    @Override
    public Boolean existAllDeviceId(Long userId, String deviceIdList) {
        if (Strings.isNullOrEmpty(deviceIdList)) return false;
        LinkedList<Long> list = new LinkedList<>();
        try {
            if (deviceIdList.indexOf(",") > 0) { // 多个设备ID
                String[] split = deviceIdList.split(",");
                List<String> deviceIds = Arrays.stream(split).collect(Collectors.toList());
                for (String deviceId : deviceIds) {

                    Long id = Long.parseLong(deviceId);
                    list.add(id);

                }
            } else list.add(Long.parseLong(deviceIdList));
        } catch (Exception e) {
            return false;
        }
        for (Long deviceId : list) {
            Device deviceByID = getDeviceByID(deviceId);
            if (deviceByID == null) return false;
            if (!deviceByID.getOwnerId().equals(userId))
                return false;
        }
        return true;
    }

    @Autowired
    DeviceService deviceService;

    @Autowired
    QuotaService quotaService;

    @Autowired
    TimeSeriesRepository timeSeriesRepository;

    @Override
    public Pager<Device> getDeviceByQuota(long userId, String quotaName, String unit, long page, long pageSize) {
        QueryWrapper<Quota> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Quota::getOwnerId, userId)
                .eq(Quota::getName, quotaName)
                .eq(Quota::getUnit, unit)
                .gt(Quota::getCreateTime, 0L);
        List<Quota> list = quotaService.list(wrapper);
        List<String> quotaIdList = list.stream().map(quota -> quota.getId() + "").collect(Collectors.toList());

        String join = String.join("|", quotaIdList);
        String fromQl = " from ( select deviceId,value from quota " +
                "where quotaId=~/^" + join + "$/ " +
                "group by deviceId,quotaId  ) ";
        String listQl = "select distinct(deviceId ) as deviceId " + fromQl +
                " limit " + pageSize + " offset " + (page - 1) * pageSize;
        String countQl = " select count( distinct(deviceId )) as count " + fromQl;

        List<QuotaInfo> quotaInfoList = timeSeriesRepository.query(listQl, QuotaInfo.class);

        //设备id列表
        List<String> deviceIdList = quotaInfoList.stream().map(QuotaInfo::getDeviceId).collect(Collectors.toList());
        LinkedList<Device> deviceList = new LinkedList<>();
        for (String deviceId : deviceIdList) {
            Device device = deviceService.getDeviceByID(Long.valueOf(deviceId));
            deviceList.add(device);
        }
        //统计记录个数
        List<QuotaCount> quotaCountList = timeSeriesRepository.query(countQl, QuotaCount.class);
        if (quotaCountList == null || quotaCountList.size() == 0) {
            Pager<Device> pager = new Pager<>(0L, 0L);
            pager.setItems(Lists.newArrayList());
            return pager;
        }
        Long count = quotaCountList.get(0).getCount();
        Pager<Device> pager = new Pager<>(count, pageSize);
        pager.setItems(deviceList);
        return pager;
    }

}
